#include <jni.h>
#include <string>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "Model.h"

#include "SystemManager.h"

static SystemManager systemManager;

//静态方式
//字符串的静态方法 和 普通方法
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_clib_NativeStaticLibProxy_stringFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "静态注册拿到String(普通方法)";
    return env->NewStringUTF(hello.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_clib_NativeStaticLibProxy_stringFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    std::string hello = "静态注册拿到String(静态方法)";
    return env->NewStringUTF(hello.c_str());
}

//short的静态方法 和 普通方法
extern "C" JNIEXPORT jshort JNICALL
Java_com_example_clib_NativeStaticLibProxy_shortFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jshort sh = 100;
    return sh;
}

extern "C" JNIEXPORT jshort JNICALL
Java_com_example_clib_NativeStaticLibProxy_shortFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jshort sh = 101;
    return sh;
}

//boolean的静态方法 和 普通方法
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_clib_NativeStaticLibProxy_booleanFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jboolean res = true;
    return res;
}

extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_clib_NativeStaticLibProxy_booleanFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jboolean res = false;
    return res;
}

//byte的静态方法 和 普通方法
extern "C" JNIEXPORT jbyte JNICALL
Java_com_example_clib_NativeStaticLibProxy_byteFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jbyte res = 10;
    return res;
}

extern "C" JNIEXPORT jbyte JNICALL
Java_com_example_clib_NativeStaticLibProxy_byteFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jbyte res = 11;
    return res;
}

//char的静态方法 和 普通方法
extern "C" JNIEXPORT jchar JNICALL
Java_com_example_clib_NativeStaticLibProxy_charFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jchar res = 'a';
    return res;
}


extern "C" JNIEXPORT jchar JNICALL
Java_com_example_clib_NativeStaticLibProxy_charFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jchar res = 'b';
    return res;
}

//int的静态方法 和 普通方法
extern "C" JNIEXPORT jint JNICALL
Java_com_example_clib_NativeStaticLibProxy_intFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jint res = 1000;
    return res;
}


extern "C" JNIEXPORT jint JNICALL
Java_com_example_clib_NativeStaticLibProxy_intFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jint res = 1001;
    return res;
}

//long的静态方法 和 普通方法
extern "C" JNIEXPORT jlong JNICALL
Java_com_example_clib_NativeStaticLibProxy_longFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jlong res = 100000;
    return res;
}


extern "C" JNIEXPORT jlong JNICALL
Java_com_example_clib_NativeStaticLibProxy_longFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jlong res = 100001;
    return res;
}

//float的静态方法 和 普通方法
extern "C" JNIEXPORT jfloat JNICALL
Java_com_example_clib_NativeStaticLibProxy_floatFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jfloat res = 1000.3333;
    return res;
}


extern "C" JNIEXPORT jfloat JNICALL
Java_com_example_clib_NativeStaticLibProxy_floatFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jfloat res = 1000.4444;
    return res;
}

//double的静态方法 和 普通方法
extern "C" JNIEXPORT jdouble JNICALL
Java_com_example_clib_NativeStaticLibProxy_doubleFromStaticJNI(
        JNIEnv* env,
        jobject /* this */) {
    jdouble res = 100000.3333333333;
    return res;
}

extern "C" JNIEXPORT jdouble JNICALL
Java_com_example_clib_NativeStaticLibProxy_doubleFromStaticJNIForStatic(
        JNIEnv* env,
        jclass cls) {
    jdouble res = 100000.4444444444;
    return res;
}

//动态方式
//字符串的静态方法 和 普通方法
jstring stringForDynamicJNI(JNIEnv *env, jobject job) {
    std::string hello = "动态注册拿到String(普通方法)";
    return env->NewStringUTF(hello.c_str());
}

jstring stringForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    std::string hello = "动态注册拿到String(静态方法)";
    return env->NewStringUTF(hello.c_str());
}

//short的静态方法 和 普通方法
jshort shortForDynamicJNI(JNIEnv *env, jobject job) {
    jshort sh = 200;
    return sh;
}

jshort shortForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jshort sh = 201;
    return sh;
}

//boolean的静态方法 和 普通方法
jboolean booleanForDynamicJNI(JNIEnv *env, jobject job) {
    jboolean res = true;
    return res;
}

jboolean booleanForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jboolean res = false;
    return res;
}

//boolean的静态方法 和 普通方法
jbyte byteForDynamicJNI(JNIEnv *env, jobject job) {
    jbyte res = 20;
    return res;
}

jbyte byteForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jbyte res = 21;
    return res;
}

//char的静态方法 和 普通方法
jchar charForDynamicJNI(JNIEnv *env, jobject job) {
    jchar res = 'c';
    return res;
}

jchar charForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jchar res = 'd';
    return res;
}

//int的静态方法 和 普通方法
jint intForDynamicJNI(JNIEnv *env, jobject job) {
    jint res = 2000;
    return res;
}

jint intForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jint res = 2001;
    return res;
}

//long的静态方法 和 普通方法
jlong longForDynamicJNI(JNIEnv *env, jobject job) {
    jlong res = 200000;
    return res;
}

jlong longForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jlong res = 200001;
    return res;
}

//float的静态方法 和 普通方法
jfloat floatForDynamicJNI(JNIEnv *env, jobject job) {
    jfloat res = 2000.6666;
    return res;
}

jfloat floatForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jfloat res = 2000.7777;
    return res;
}

//double的静态方法 和 普通方法
jdouble doubleForDynamicJNI(JNIEnv *env, jobject job) {
    jdouble res = 200000.6666666666;
    return res;
}

jdouble doubleForDynamicJNIForStatic(JNIEnv *env, jclass cls) {
    jdouble res = 200000.7777777777;
    return res;
}

static JNINativeMethod methodsMap[] = {
        //String
        {"stringFromDynamicJNI","()Ljava/lang/String;",(void *)stringForDynamicJNI},
        {"stringFromDynamicJNIForStatic","()Ljava/lang/String;",(void *)stringForDynamicJNIForStatic},
        //short
        {"shortFromDynamicJNI","()S",(void *)shortForDynamicJNI},
        {"shortFromDynamicJNIForStatic","()S",(void *)shortForDynamicJNIForStatic},
        //boolean
        {"booleanFromDynamicJNI","()Z",(void *)booleanForDynamicJNI},
        {"booleanFromDynamicJNIForStatic","()Z",(void *)booleanForDynamicJNIForStatic},
        //byte
        {"byteFromDynamicJNI","()B",(void *)byteForDynamicJNI},
        {"byteFromDynamicJNIForStatic","()B",(void *)byteForDynamicJNIForStatic},
        //char
        {"charFromDynamicJNI","()C",(void *)charForDynamicJNI},
        {"charFromDynamicJNIForStatic","()C",(void *)charForDynamicJNIForStatic},
        //int
        {"intFromDynamicJNI","()I",(void *)intForDynamicJNI},
        {"intFromDynamicJNIForStatic","()I",(void *)intForDynamicJNIForStatic},
        //long
        {"longFromDynamicJNI","()J",(void *)longForDynamicJNI},
        {"longFromDynamicJNIForStatic","()J",(void *)longForDynamicJNIForStatic},
        //float
        {"floatFromDynamicJNI","()F",(void *)floatForDynamicJNI},
        {"floatFromDynamicJNIForStatic","()F",(void *)floatForDynamicJNIForStatic},
        //double
        {"doubleFromDynamicJNI","()D",(void *)doubleForDynamicJNI},
        {"doubleFromDynamicJNIForStatic","()D",(void *)doubleForDynamicJNIForStatic},
};


jstring  nativeStrSplicing(JNIEnv *env, jobject job, jstring mes) {
    const char* cMes = env->GetStringUTFChars(mes, 0);
    const char* temp = "Native Str";
    int totalLength = 0;
    totalLength = strlen(cMes) + strlen(temp) + 1;
    char resStr[totalLength];
    if (cMes != NULL) {
        strcpy(resStr, cMes);
        strcpy(resStr, temp);
        env->ReleaseStringUTFChars(mes,cMes);
        return env->NewStringUTF(resStr);
    } else {
        const char* temp = "Native Error";
        env->ReleaseStringUTFChars(mes,cMes);
        return env->NewStringUTF(temp);
    }
}

jboolean nativeStrCompare(JNIEnv *env, jobject job, jstring str1, jstring str2) {
    const char* cStr1 = env->GetStringUTFChars(str1,0);
    const char* cStr2 = env->GetStringUTFChars(str2,0);
    int str1Length = strlen(cStr1);
    int str2Length = strlen(cStr2);
    if (str1Length != str2Length) {
        env->ReleaseStringUTFChars(str1,cStr1);
        env->ReleaseStringUTFChars(str2,cStr2);
        return false;
    }

    jboolean res = true;
    for (int i = 0; i < str1Length; ++i) {
        if (cStr1[i] != cStr2[i]) {
            res = false;
            break;
        }
    }
    env->ReleaseStringUTFChars(str1,cStr1);
    env->ReleaseStringUTFChars(str2,cStr2);
    return res;
}

jobjectArray nativeStrArray(JNIEnv *env, jobject job, jstring p1, jstring p2, jstring p3, jstring p4, jstring p5, jstring p6, jstring p7, jstring p8, jstring p9, jint size) {
    jclass strCls = env->FindClass("java/lang/String");
    jobjectArray source = env->NewObjectArray(size,strCls,NULL);

    env->SetObjectArrayElement(source,0,p1);
    env->SetObjectArrayElement(source,1,p2);
    env->SetObjectArrayElement(source,2,p3);
    env->SetObjectArrayElement(source,3,p4);
    env->SetObjectArrayElement(source,4,p5);
    env->SetObjectArrayElement(source,5,p6);
    env->SetObjectArrayElement(source,6,p7);
    env->SetObjectArrayElement(source,7,p8);
    env->SetObjectArrayElement(source,8,p9);
    jobjectArray res = env->NewObjectArray(size,strCls,NULL);
    if (res == NULL) {
        return NULL;
    }
    char buf[20];
    jstring str;
    for (int i = 0; i < size; i++) {
        str = static_cast<jstring>(env->GetObjectArrayElement(source, i));
        const char * mStr = env->GetStringUTFChars(str,0);
        snprintf(buf,sizeof(buf),"%s-%d",mStr,i);
        env ->SetObjectArrayElement(res, i, env->NewStringUTF(buf));
        env->ReleaseStringUTFChars(str,mStr);
    }

    return res;
}


static JNINativeMethod methodsMapForString[] = {
        //String
        {"strSplicing","(Ljava/lang/String;)Ljava/lang/String;",(void *)nativeStrSplicing},
        {"strCompare","(Ljava/lang/String;Ljava/lang/String;)Z",(void *)nativeStrCompare},
        {"strArray","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)[Ljava/lang/String;",(void *)nativeStrArray},
};

// Byte数组排序
jbyteArray nativeByteSort(JNIEnv *env, jobject job, jbyteArray array) {
    jbyte * byteArray = env->GetByteArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jbyteArray res = env->NewByteArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jbyte temp = byteArray[j];
            if (byteArray[j] < byteArray[j+1]) {
                byteArray[j] = byteArray[j+1];
                byteArray[j+1] = temp;
            }
        }
    }
    env->SetByteArrayRegion(res,0,size,byteArray);
    env->ReleaseByteArrayElements(array,byteArray,0);
    return res;
}

// Short数组排序
jshortArray nativeShortSort(JNIEnv *env, jobject job, jshortArray array) {
    jshort * shortArray = env->GetShortArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jshortArray res = env->NewShortArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jshort temp = shortArray[j];
            if (shortArray[j] < shortArray[j+1]) {
                shortArray[j] = shortArray[j+1];
                shortArray[j+1] = temp;
            }
        }
    }
    env->SetShortArrayRegion(res,0,size,shortArray);
    env->ReleaseShortArrayElements(array,shortArray,0);
    return res;
}

// Int数组排序
jintArray nativeIntSort(JNIEnv *env, jobject job, jintArray array) {
    jint * intArray = env->GetIntArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jintArray res = env->NewIntArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jint temp = intArray[j];
            if (intArray[j] < intArray[j+1]) {
                intArray[j] = intArray[j+1];
                intArray[j+1] = temp;
            }
        }
    }
    env->SetIntArrayRegion(res,0,size,intArray);
    env->ReleaseIntArrayElements(array,intArray,0);
    return res;
}

// Long数组排序
jlongArray nativeLongSort(JNIEnv *env, jobject job, jlongArray array) {
    jlong * longArray = env->GetLongArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jlongArray res = env->NewLongArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jlong temp = longArray[j];
            if (longArray[j] < longArray[j+1]) {
                longArray[j] = longArray[j+1];
                longArray[j+1] = temp;
            }
        }
    }
    env->SetLongArrayRegion(res,0,size,longArray);
    env->ReleaseLongArrayElements(array,longArray,0);
    return res;
}

// Float数组排序
jfloatArray nativeFloatSort(JNIEnv *env, jobject job, jfloatArray array) {
    jfloat  * floatArray = env->GetFloatArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jfloatArray res = env->NewFloatArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jfloat temp = floatArray[j];
            if (floatArray[j] < floatArray[j+1]) {
                floatArray[j] = floatArray[j+1];
                floatArray[j+1] = temp;
            }
        }
    }
    env->SetFloatArrayRegion(res,0,size,floatArray);
    env->ReleaseFloatArrayElements(array,floatArray,0);
    return res;
}

// Double数组排序
jdoubleArray nativeDoubleSort(JNIEnv *env, jobject job, jdoubleArray array) {
    jdouble * doubleArray = env->GetDoubleArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jdoubleArray res = env->NewDoubleArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jdouble temp = doubleArray[j];
            if (doubleArray[j] < doubleArray[j+1]) {
                doubleArray[j] = doubleArray[j+1];
                doubleArray[j+1] = temp;
            }
        }
    }
    env->SetDoubleArrayRegion(res,0,size,doubleArray);
    env->ReleaseDoubleArrayElements(array,doubleArray,0);
    return res;
}

// Boolean数组排序
jbooleanArray nativeBooleanSort(JNIEnv *env, jobject job, jbooleanArray array) {
    jboolean * booleanArray = env->GetBooleanArrayElements(array,0);
    jsize size = env->GetArrayLength(array);
    jbooleanArray res = env->NewBooleanArray(size);
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size - 1; ++j) {
            jboolean temp = booleanArray[j];
            if (booleanArray[j] < booleanArray[j+1]) {
                booleanArray[j] = booleanArray[j+1];
                booleanArray[j+1] = temp;
            }
        }
    }
    env->SetBooleanArrayRegion(res,0,size,booleanArray);
    env->ReleaseBooleanArrayElements(array,booleanArray,0);
    return res;
}

static JNINativeMethod methodsMapForArray[] = {
        {"byteSort","([B)[B",(void *)nativeByteSort},
        {"shortSort","([S)[S",(void *)nativeShortSort},
        {"intSort","([I)[I",(void *)nativeIntSort},
        {"longSort","([J)[J",(void *)nativeLongSort},
        {"floatSort","([F)[F",(void *)nativeFloatSort},
        {"doubleSort","([D)[D",(void *)nativeDoubleSort},
        {"booleanSort","([Z)[Z",(void *)nativeBooleanSort},
};

jclass getClassByName(JNIEnv *env, const char * cls) {
    jclass jCls = env->FindClass(cls);
    return jCls;
}

//native访问java类字段/方法
// 获取静态字段（Java面向语言的封装性对JNI无效）

//获取静态byte字段
jbyte nativeGetTestModelStaticFiledByte(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID byteFiledId = env->GetStaticFieldID(jCls,"byteValue","B");
    jbyte res = env->GetStaticByteField(jCls,byteFiledId);
    return res;
}

//获取静态short字段
jshort nativeGetTestModelStaticFiledShort(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID shortFiledId = env->GetStaticFieldID(jCls,"shortValue","S");
    jshort res = env->GetStaticShortField(jCls,shortFiledId);
    return res;
}

//获取静态int字段
jint nativeGetTestModelStaticFiledInt(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID intFiledId = env->GetStaticFieldID(jCls,"intValue","I");
    jint res = env->GetStaticIntField(jCls,intFiledId);
    return res;
}

//获取静态long字段
jlong nativeGetTestModelStaticFiledLong(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID longFiledId = env->GetStaticFieldID(jCls,"longValue","J");
    jlong res = env->GetStaticLongField(jCls,longFiledId);
    return res;
}

//获取静态float字段
jfloat nativeGetTestModelStaticFiledFloat(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID floatFiledId = env->GetStaticFieldID(jCls,"floatValue","F");
    jfloat res = env->GetStaticFloatField(jCls,floatFiledId);
    return res;
}

//获取静态double字段
jdouble nativeGetTestModelStaticFiledDouble(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID doubleFiledId = env->GetStaticFieldID(jCls,"doubleValue","D");
    jdouble res = env->GetStaticDoubleField(jCls,doubleFiledId);
    return res;
}

//获取静态char字段
jchar nativeGetTestModelStaticFiledChar(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID charFiledId = env->GetStaticFieldID(jCls,"charValue","C");
    jchar res = env->GetStaticCharField(jCls,charFiledId);
    return res;
}

//获取静态boolean字段
jboolean nativeGetTestModelStaticFiledBoolean(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return -1;
    }

    jfieldID booleanFiledId = env->GetStaticFieldID(jCls,"booleanValue","Z");
    jboolean res = env->GetStaticBooleanField(jCls,booleanFiledId);
    return res;
}

//获取静态Model2字段
jobject nativeGetTestModelStaticFiledModel2(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return NULL;
    }

    jfieldID model2FiledId = env->GetStaticFieldID(jCls,"model2Value","Lcom/example/clib/model/Model2;");
    jobject res = env->GetStaticObjectField(jCls,model2FiledId);
    return res;
}

//获取静态string数组字段
 jobjectArray nativeGetTestModelStaticFiledStringArray(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return NULL;
    }

    jfieldID stringArrayFiledId = env->GetStaticFieldID(jCls,"stringArrayValue","[Ljava/lang/String;");
    jobjectArray res = static_cast<jobjectArray>(env->GetStaticObjectField(jCls,stringArrayFiledId));
    return res;
}

//调用静态方法
jstring nativeGetTestModelStaticMethod(JNIEnv *env, jobject job) {
    jclass jCls = env->FindClass("com/example/clib/model/TestModel");
    if (jCls == NULL) {
        return NULL;
    }

    jfieldID byteFiledId = env->GetStaticFieldID(jCls,"byteValue","B");
    jfieldID shortFiledId = env->GetStaticFieldID(jCls,"shortValue","S");
    jfieldID intFiledId = env->GetStaticFieldID(jCls,"intValue","I");
    jfieldID longFiledId = env->GetStaticFieldID(jCls,"longValue","J");
    jfieldID floatFiledId = env->GetStaticFieldID(jCls,"floatValue","F");
    jfieldID doubleFiledId = env->GetStaticFieldID(jCls,"doubleValue","D");
    jfieldID charFiledId = env->GetStaticFieldID(jCls,"charValue","C");
    jfieldID booleanFiledId = env->GetStaticFieldID(jCls,"booleanValue","Z");

    env->SetStaticByteField(jCls,byteFiledId,11);
    env->SetStaticShortField(jCls,shortFiledId,110);
    env->SetStaticIntField(jCls,intFiledId,1110);
    jlong longValue = 11110;
    env->SetStaticLongField(jCls,longFiledId,longValue);
    jfloat floatValue = 1110.6666;
    env->SetStaticFloatField(jCls,floatFiledId,floatValue);
    env->SetStaticDoubleField(jCls,doubleFiledId,111110.6666666666);
    env->SetStaticCharField(jCls,charFiledId,'z');
    env->SetStaticBooleanField(jCls,booleanFiledId,false);

    jmethodID methodId = env->GetStaticMethodID(jCls,"getStaticFiledCollectionStr","()Ljava/lang/String;");
    jstring res = static_cast<jstring>(env->CallStaticObjectMethod(jCls, methodId));
    return res;
}

//使用构造方法初始化
jobject nativeGetTestModelObject(JNIEnv *env, jobject job) {
    jclass testModelCls = env->FindClass("com/example/clib/model/TestModel");
    if (testModelCls == NULL) {
        return NULL;
    }

    jmethodID initMethod = env->GetMethodID(testModelCls, "<init>", "()V");
    if (initMethod == NULL) {
        return NULL;
    }

    jobject testModel = env->NewObject(testModelCls,initMethod);
    return testModel;
}

//得到普通基本数据类型字段
jint nativeGetTestModelFiledInt(JNIEnv *env, jobject job, jobject testModel) {
    jfieldID intValue = env->GetFieldID(env->GetObjectClass(testModel),"mIntValue","I");
    jint res = env->GetIntField(testModel,intValue);
    return res;
}

//得到普通对象字段并赋值
jobject nativeGetTestModelFiledModel2(JNIEnv *env, jobject job, jobject testModel) {
    jfieldID model2Value = env->GetFieldID(env->GetObjectClass(testModel),"mModel2Value","Lcom/example/clib/model/Model2;");

    //创建一个Model2的对象
    jclass jCls = env->FindClass("com/example/clib/model/Model2");
    jmethodID initMethod = env->GetMethodID(jCls,"<init>","()V");
    jobject jmodel2 = env->NewObject(jCls,initMethod);
    //设置值
    env->SetObjectField(testModel,model2Value,jmodel2);
    //取值
    jobject model2 = env->GetObjectField(testModel,model2Value);
    return model2;
}

//调用对象的普通方法
jstring nativeGetTestModelMethod(JNIEnv *env, jobject job, jobject testModel) {
    jmethodID normalMethod = env->GetMethodID(env->GetObjectClass(testModel),"getObjectHashCode","()Ljava/lang/String;");
    if (normalMethod == NULL) {
        return NULL;
    }
    jstring res = static_cast<jstring>(env->CallObjectMethod(testModel, normalMethod));
    return res;
}

static JNINativeMethod methodsMapForObject[] = {
        {"getTestModelStaticFiledByte","()B",(void *)nativeGetTestModelStaticFiledByte},
        {"getTestModelStaticFiledShort","()S",(void *)nativeGetTestModelStaticFiledShort},
        {"getTestModelStaticFiledInt","()I",(void *)nativeGetTestModelStaticFiledInt},
        {"getTestModelStaticFiledLong","()J",(void *)nativeGetTestModelStaticFiledLong},
        {"getTestModelStaticFiledFloat","()F",(void *)nativeGetTestModelStaticFiledFloat},
        {"getTestModelStaticFiledDouble","()D",(void *)nativeGetTestModelStaticFiledDouble},
        {"getTestModelStaticFiledChar","()C",(void *)nativeGetTestModelStaticFiledChar},
        {"getTestModelStaticFiledBoolean","()Z",(void *)nativeGetTestModelStaticFiledBoolean},
        {"getTestModelStaticFiledModel2","()Lcom/example/clib/model/Model2;",(void *)nativeGetTestModelStaticFiledModel2},
        {"getTestModelStaticFiledStringArray","()[Ljava/lang/String;",(void *)nativeGetTestModelStaticFiledStringArray},
        {"getTestModelStaticMethod","()Ljava/lang/String;",(void *)nativeGetTestModelStaticMethod},
        {"getTestModelObject","()Lcom/example/clib/model/TestModel;",(void *)nativeGetTestModelObject},
        {"getTestModelFiledInt","(Lcom/example/clib/model/TestModel;)I",(void *)nativeGetTestModelFiledInt},
        {"getTestModelFiledModel2","(Lcom/example/clib/model/TestModel;)Lcom/example/clib/model/Model2;",(void *)nativeGetTestModelFiledModel2},
        {"getTestModelMethod","(Lcom/example/clib/model/TestModel;)Ljava/lang/String;",(void *)nativeGetTestModelMethod},
};

void nativeThrowExceptionFormJNI(JNIEnv *env, jobject job) {
    jthrowable exc;
    jmethodID methodId = env->GetMethodID(env->GetObjectClass(job),"hello","()V");
    exc = env->ExceptionOccurred();
    if (exc) {
        jclass newExcCls;
        env->ExceptionDescribe();
        env->ExceptionClear();
        newExcCls = env->FindClass("java/lang/NoSuchMethodException");
        if (newExcCls == NULL) {
            /* Unable to find the exception class, give up. */
            return;
        }
        env->ThrowNew(newExcCls, "thrown from C code");
    }
}

void nativeThrowException(JNIEnv *env, jobject job) {
    jthrowable exc;
    jmethodID methodId = env->GetMethodID(env->GetObjectClass(job),"hello","()V");

}

jstring nativeGetCurrentEnvAddress(JNIEnv *env, jobject job) {
    char buf[100];
    snprintf(buf,sizeof(buf),"%s-%p","当前env地址为",&env);
    jstring res = env->NewStringUTF(buf);
    return res;
}

static JNINativeMethod methodMapForException[] {
        {"throwExceptionFormJNI","()V",(void *)nativeThrowExceptionFormJNI},
        {"throwException","()V",(void *)nativeThrowException},
        {"getCurrentEnvAddress","()Ljava/lang/String;",(void *)nativeGetCurrentEnvAddress},
};


jstring nativePrintSizeInfo(JNIEnv *env, jobject job) {
    const char * res = systemManager.getSizeOfType();
    jstring jRes = env->NewStringUTF(res);
    __android_log_print(ANDROID_LOG_INFO,"native_log","ReleaseStringUTFChars之后两个参数的地址 res = %p jRes = %p",res,jRes);
    return jRes;
}

jstring nativeFreePointTest(JNIEnv *env, jobject job) {
    const char * res = systemManager.freeTest();
    jstring jRes = env->NewStringUTF(res);
    return jRes;
}

static JNINativeMethod methodMapForCpp[] {
        {"printSizeInfo","()Ljava/lang/String;",(void *)nativePrintSizeInfo},
        {"freePointTest","()Ljava/lang/String;",(void *)nativeFreePointTest},
};

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    //注册单个java类
    //注册时在JNIEnv中实现的，所以必须先获取它
    JNIEnv *env = NULL;
    jint res = -1;
    //从Java中获取JNIEnv, 一般使用 1.4版本
    if ((*vm).GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        return res;
    }

    //注册单个java类  基本数据类型 和 String基础
    jclass dynamicProxyCls;
    static const char* const dynamicProxyClassName = "com/example/clib/NativeDynamicLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    dynamicProxyCls = env->FindClass(dynamicProxyClassName);

    if (dynamicProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/NativeDynamicLibProxy");
        return res;
    }

    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(dynamicProxyCls,methodsMap,sizeof(methodsMap)/sizeof(methodsMap[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for dynamicProxyCls");
        return res;
    }

    //注册第二个java类  String相关操作
    jclass stringOpProxyCls;
    static const char* const stringOpProxyClassName = "com/example/clib/StringOpLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    stringOpProxyCls = env->FindClass(stringOpProxyClassName);

    if (stringOpProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/StringOpLibProxy");
        return res;
    }

    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(stringOpProxyCls,methodsMapForString,sizeof(methodsMapForString)/sizeof(methodsMapForString[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for stringOpProxyCls");
        return res;
    }

    //注册第三个java类  数组相关操作
    jclass arrayOpProxyCls;
    static const char* const arrayOpProxyClassName = "com/example/clib/ArrayOpLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    arrayOpProxyCls = env->FindClass(arrayOpProxyClassName);

    if (arrayOpProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/ArrayOpLibProxy");
        return res;
    }

    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(arrayOpProxyCls,methodsMapForArray,sizeof(methodsMapForArray)/sizeof(methodsMapForArray[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for arrayOpProxyCls");
        return res;
    }

    //注册第四个java类  类和对象相关操作
    jclass objectOpProxyCls;
    static const char* const objectOpProxyClassName = "com/example/clib/ObjectOpLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    objectOpProxyCls = env->FindClass(objectOpProxyClassName);

    if (objectOpProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/ObjectOpLibProxy");
        return res;
    }

    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(objectOpProxyCls,methodsMapForObject,sizeof(methodsMapForObject)/sizeof(methodsMapForObject[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for objectOpProxyCls");
        return res;
    }

    //注册第五个java类  异常和线程相关操作
    jclass exceptionOpProxyCls;
    static const char* const exceptionOpProxyClassName = "com/example/clib/ExceptionOpLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    exceptionOpProxyCls = env->FindClass(exceptionOpProxyClassName);

    if (exceptionOpProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/ExceptionOpLibProxy");
        return res;
    }

    __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method for exceptionOpProxyCls env address = %p",&env);
    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(exceptionOpProxyCls,methodMapForException,sizeof(methodMapForException)/sizeof(methodMapForException[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for exceptionOpProxyCls");
        return res;
    }

    //注册第六个java类  使用c++语法
    jclass cppOpProxyCls;
    static const char* const cppOpProxyClsName = "com/example/clib/CppOpLibProxy";
    //这里可以找到要注册的类，前提是这个类已经加载到java虚拟机中。 这里说明，动态库和有native方法的类之间，没有任何对应关系。
    cppOpProxyCls = env->FindClass(cppOpProxyClsName);

    if (cppOpProxyCls == NULL) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: cannot get class: com/example/clib/CppOpLibProxy");
        return res;
    }

    __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method for CppOpLibProxy env address = %p",&env);
    //注册Java Native方法与Jni方法的对应表
    if (env->RegisterNatives(cppOpProxyCls,methodMapForCpp,sizeof(methodMapForCpp)/sizeof(methodMapForCpp[0])) != JNI_OK) {
        __android_log_print(ANDROID_LOG_INFO,"native_log","JNI_OnLoad: register native method failed! for CppOpLibProxy");
        return res;
    }
    return JNI_VERSION_1_4;
}

